// const express = require('express');
// 需要在package.json中配置type: module才能使用es6模块化语法
import express from "express";
import axios from "axios";
import jwt from "jsonwebtoken";
import "./db/index.js";
import Users from "./db/models/users.js";
// 创建app应用对象
const app = express();

// 解析请求体数据
app.use(express.json());

const JWT_SECRET = "2d@ssQ22z#sws32/";

const whiteList = ["/loginByWeixin"];

// 中间件，所有请求都会走中间件
app.use((req, res, next) => {
  try {
    if (whiteList.includes(req.url)) {
      next();
      return;
    }
    const token = req.headers.token;
    const { openid } = jwt.verify(token, JWT_SECRET);
    req.query.openid = openid;
    next();
  } catch (e) {
    res.status(401);
    if (e.message === "jwt expired") {
      res.send("token过期了");
      return;
    }
    res.send("无效的token");
  }
});

// 配置后端路由
// 向外暴露一个接口（API），前端就可以访问这个接口
app.post("/loginByWeixin", async (req, res) => {
  /*
    req 请求对象（里面包含所有请求信息：请求来源地址、请求方式、请求参数、请求头等）
      从前端获取内容，从req中读取
        如何请求请求参数
          req.params --> 获取路径参数path /trademark/1/10
          req.query --> 获取查询字符串参数query /xxx?key=value
          req.body --> 获取请求体参数body (请求体需要解析才能获取，需要使用中间件)
          req.headers --> req.headers.token
          req.cookies --> req.cookies.MUSIC_U (cookie需要解析才能获取，需要使用中间件)
    res 响应对象（里面包含所有给客户端的响应信息）
      要返回数据给前端，从res中设置
        res.status(401) 设置响应状态码
        res.send() 响应数据给前端（通用）
        res.json() 响应数据给前端（对象/数组数据）

    安装一个包：
      npm i nodemon -g
      当我们修改服务器代码，会自动重启服务器。
      使用：
        nodemon server.js
  */
  // 得到code和用户数据
  /*
    {
      code: '071c0Kml2gOFda49Z6ml2C8lEn2c0Kmy',
      userInfo: {
        nickName: '微信用户',
        gender: 0,
        language: '',
        city: '',
        province: '',
        country: '',
        avatarUrl: 'https://thirdwx.qlogo.cn/mmopen/vi_32/POgEwh4mIHO4nibH0KlMECNjjGxQUq24ZEaGT4poC6icRiccVGKSyXwibcPq4BWmiaIGuG1icwxaQX6grC9VemZoJ8rg/132'
      }
    }
  */
  const { code, userInfo } = req.body;
  // console.log(body);
  // 4. 通过code、appid、appsecret等参数去微信服务器请求用户数据
  const result = await axios.get(
    "https://api.weixin.qq.com/sns/jscode2session",
    {
      params: {
        appid: "wx3928e5f699a4539f",
        secret: "fc6a3d3a6533fd8a20a8be4a327a87f0",
        js_code: code,
        grant_type: "authorization_code",
      },
    }
  );

  /*
    {
      session_key: 'mLaE9W177zSuycqgOpaLlA==',
      openid: 'oOivj5UD0Pty_V5pgS4I457HRFN4'
    }
  */
  const { openid } = result.data;

  // 加密，生成token
  const token = jwt.sign({ openid }, JWT_SECRET, { expiresIn: "7d" });
  // eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJvcGVuaWQiOiJvT2l2ajVVRDBQdHlfVjVwZ1M0STQ1N0hSRk40IiwiaWF0IjoxNjY3OTgwNzI5LCJleHAiOjE2Njg1ODU1Mjl9.he8WYN5arMZPSOSqd5XV0HJr1aQI-1TbMCnt5xvN5e8
  // console.log(token);
  // 将用户数据 openid token一起存储起来
  /*  
    数据库：
      增 create
      删 deleteOne deleteMany
      改 updateOne updateMany
      查 find findOne
  */
  const user = await Users.findOne({ openid });
  if (user) {
    user.token = token;
    await user.save();
  } else {
    await Users.create({
      token,
      openid,
      nickName: userInfo.nickName,
      avatarUrl: userInfo.avatarUrl,
    });
  }

  // 返回响应
  res.json({
    code: 200,
    success: true,
    message: "",
    data: {
      token,
    },
  });
});

app.get("/getUserInfo", async (req, res) => {

  const openid = req.query.openid;

  const user = await Users.findOne(
    { openid },
    { nickName: 1, avatarUrl: 1, _id: 0 }
  );

  res.json({
    code: 200,
    success: true,
    message: "",
    data: user,
  });
});

// app.get("/getUserInfo", async (req, res) => {
//   try {
//     const token = req.headers.token;
//     // 解密（解密的同时会验证token是否合法：是否有效&是否过期）
//     // 解密成功，会返回参与加密的数据
//     // 解密失败，函数会报错
//     const { openid } = jwt.verify(token, JWT_SECRET);
//     /*
//       {
//         openid: 'oOivj5UD0Pty_V5pgS4I457HRFN4',
//         iat: 1667982305,
//         exp: 1668587105
//       }
//     */
//     const user = await Users.findOne(
//       { openid },
//       { nickName: 1, avatarUrl: 1, _id: 0 }
//     );

//     res.json({
//       code: 200,
//       success: true,
//       message: "",
//       data: user,
//     });
//   } catch (e) {
//     // console.log(e.message); // invalid token // jwt expired
//     res.status(401);
//     if (e.message === "jwt expired") {
//       res.send("token过期了");
//       return;
//     }
//     res.send("无效的token");
//   }
// });

// 启动服务（监听端口号）
app.listen(5000, "localhost", (err) => {
  if (err) console.log(err);
  else console.log("服务器启动成功");
});
